package proxy;

import java.io.*;
import java.net.*;
import java.security.*;
import java.util.*;
import javax.net.*;
import javax.net.ssl.*;

public class ServerProxy {
	public static void main(String[] args) throws Exception { new ServerProxy(4441, 3306); }
	private SSLContext sslContext;
	private SecureRandom secureRandom;
	private Socket client, serv;
	
	public ServerProxy(int listenport, int serverport) throws Exception {
	    System.out.println( "Wait while secure random numbers are initialized...." );
	    secureRandom = new SecureRandom();
	    secureRandom.nextInt();
	    System.out.println( "Done." );
		
		setupKeyStoresAndSSLContext();
		
		SSLServerSocketFactory sf = sslContext.getServerSocketFactory();
		SSLServerSocket listen = (SSLServerSocket)sf.createServerSocket( listenport );
		
		listen.setNeedClientAuth( true );
		
		while (true) {
			System.out.println("waiting for client...");
			client = listen.accept();
			InputStream cliin = client.getInputStream();
			OutputStream cliout = client.getOutputStream();
			System.out.println("got client");
			
			System.out.println("setting up server connection...");
			serv = new Socket("localhost", serverport);
			InputStream servin = serv.getInputStream();
			OutputStream servout = serv.getOutputStream();
			System.out.println("connected to server");
			
			Thread a = new Thread(new Listener(cliin, servout));
			Thread b = new Thread(new Listener(servin, cliout));
			
			a.start();
			b.start();
		}
	}
	
	public void close() {
		try {
			client.close();
			serv.close();
		} catch (IOException e) { }
		System.out.println("closed connection");
	}
	private class Listener implements Runnable {
		private InputStream src;
		private OutputStream dest;

		public Listener(InputStream source, OutputStream destination) {
			src = source;
			dest = destination;
		}

		@Override
		public void run() {
			try {
				int i;
				while ((i = src.read()) != -1) {
					dest.write(i);
				}
			} catch (Exception e) {
			}
			close();
		}
	}
	
  private void setupKeyStoresAndSSLContext() throws GeneralSecurityException, IOException {
    String passphrase="serverpw";
    KeyStore serverKeyStore;
    KeyStore clientKeyStore;
    clientKeyStore = KeyStore.getInstance( "JKS" );
    clientKeyStore.load( new FileInputStream( "../client.public" ),
                       "public".toCharArray() );
    
    serverKeyStore = KeyStore.getInstance( "JKS" );
	serverKeyStore.load( new FileInputStream( "../server.private" ),
                        passphrase.toCharArray() );

    TrustManagerFactory tmf = TrustManagerFactory.getInstance( "SunX509" );
    tmf.init( clientKeyStore );

    KeyManagerFactory kmf = KeyManagerFactory.getInstance( "SunX509" );
    kmf.init( serverKeyStore, passphrase.toCharArray() );

    sslContext = SSLContext.getInstance( "TLS" );
    sslContext.init( kmf.getKeyManagers(), tmf.getTrustManagers(), secureRandom );
  }

}
